<template>
	<div
		id="cesium-dom"
		class="cesium-content"
	/>
</template>

<script setup lang="ts">
import * as cesium from "cesium";
import "@cesium/widgets/Source/widgets.css";
import model from "@/model/bell206_helicopter.glb";

cesium.Ion.defaultAccessToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI0OTBmMzllMy0yYjgzLTQ1YmUtYjNlNi1iOGRhODdhYzkzODMiLCJpZCI6MzYxNjQyLCJpYXQiOjE3NjM1MTgzMTd9.cPtinfeWhfpRWc7Phcm--JhCSqF4pdBcVUDbi4bhvPI";

onMounted(async () => {
	const viewer = new cesium.Viewer("cesium-dom", {
		animation: true,
		timeline: true,
		baseLayerPicker: false,
		terrain: cesium.Terrain.fromWorldTerrain({
			requestWaterMask: true,
			requestVertexNormals: true,
		}),
	});

	viewer.scene.globe.enableLighting = true;

	/**
	 * @description 添加全球建筑物 3D Tiles（暂时不设置样式）
	 * */
	try {
		const osmBuildings = await cesium.createOsmBuildingsAsync();
		viewer.scene.primitives.add(osmBuildings);
		console.log('建筑物加载成功');
	} catch (error) {
		console.warn('建筑物加载失败:', error);
	}

	/**
	 * @description 添加建筑物点击交互
	 * */
	const handler = new cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
	let selectedBuilding: cesium.Cesium3DTileFeature | null = null;

	handler.setInputAction((movement: cesium.ScreenSpaceEventHandler.PositionedEvent) => {
		// 恢复之前选中的建筑颜色
		if (selectedBuilding) {
			selectedBuilding.color = cesium.Color.WHITE.withAlpha(0.6);
		}

		// 拾取新建筑
		const pickedFeature = viewer.scene.pick(movement.position);
		if (cesium.defined(pickedFeature) && pickedFeature instanceof cesium.Cesium3DTileFeature) {
			selectedBuilding = pickedFeature;
			// 高亮为亮黄色
			selectedBuilding.color = cesium.Color.YELLOW;

			// 打印建筑信息
			const name = pickedFeature.getProperty('name') || '未命名建筑';
			const height = pickedFeature.getProperty('building:height') || '未知';
			const buildingType = pickedFeature.getProperty('building') || '未知类型';
			console.log(`建筑: ${name}, 高度: ${height}米, 类型: ${buildingType}`);
		}
	}, cesium.ScreenSpaceEventType.LEFT_CLICK);

	/**
	 * @description 定位位置 - 等待地形数据加载
	 * */
	const longitude = 116.39;
	const latitude = 39.9;

	// 创建地理坐标
	const cartographic = cesium.Cartographic.fromDegrees(longitude, latitude);

	// 等待地形数据加载完成
	let terrainHeight = 50; // 默认高度（北京市区平均海拔）
	try {
		const terrainSamples = await cesium.sampleTerrainMostDetailed(viewer.terrainProvider, [cartographic]);
		if (terrainSamples && terrainSamples.length > 0 && terrainSamples[0].height !== undefined) {
			terrainHeight = terrainSamples[0].height;
		}
		console.log('获取到的地形高度:', terrainHeight);
	} catch (error) {
		console.warn('获取地形高度失败，使用默认值:', error);
	}

	/**
	 * @description 创建飞行路径 - 先垂直起飞，然后沿圆形路径飞行
	 * */
	const startTime = cesium.JulianDate.now();
	const takeoffDuration = 10; // 起飞时间10秒
	const flightDuration = 360; // 飞行时间360秒
	const totalDuration = takeoffDuration + flightDuration;
	const stopTime = cesium.JulianDate.addSeconds(startTime, totalDuration, new cesium.JulianDate());

	// 设置时钟
	viewer.clock.startTime = startTime.clone();
	viewer.clock.stopTime = stopTime.clone();
	viewer.clock.currentTime = startTime.clone();
	viewer.clock.clockRange = cesium.ClockRange.LOOP_STOP; // 循环播放
	viewer.clock.multiplier = 1; // 时间倍速，1表示实时

	// 创建位置属性
	const positionProperty = new cesium.SampledPositionProperty();

	const radius = 0.01; // 圆形半径（经纬度单位）
	const flightHeight = terrainHeight + 100; // 飞行高度
	const groundHeight = terrainHeight + 2; // 地面高度（略高于地面）

	// 1. 起飞阶段：从地面垂直上升到飞行高度
	const takeoffSteps = 5; // 起飞分5个步骤
	for (let i = 0; i <= takeoffSteps; i++) {
		const time = cesium.JulianDate.addSeconds(startTime, (i / takeoffSteps) * takeoffDuration, new cesium.JulianDate());
		const height = groundHeight + (flightHeight - groundHeight) * (i / takeoffSteps);
		const position = cesium.Cartesian3.fromDegrees(longitude, latitude, height);
		positionProperty.addSample(time, position);
	}

	// 2. 飞行阶段：沿圆形路径飞行
	const flightStartTime = cesium.JulianDate.addSeconds(startTime, takeoffDuration, new cesium.JulianDate());
	for (let i = 0; i <= flightDuration; i += 10) {
		const time = cesium.JulianDate.addSeconds(flightStartTime, i, new cesium.JulianDate());
		const angle = (i / flightDuration) * Math.PI * 2; // 角度

		const lon = longitude + radius * Math.cos(angle);
		const lat = latitude + radius * Math.sin(angle);
		const position = cesium.Cartesian3.fromDegrees(lon, lat, flightHeight);

		positionProperty.addSample(time, position);
	}

	// 设置插值方式为线性插值，使运动更平滑
	positionProperty.setInterpolationOptions({
		interpolationDegree: 1,
		interpolationAlgorithm: cesium.LinearApproximation,
	});

	/**
	 * @description 创建自定义朝向属性
	 * 让模型头部始终朝向运动方向，并可以添加额外的旋转偏移
	 * */
	const velocityOrientation = new cesium.VelocityOrientationProperty(positionProperty);

	// 调整模型的朝向偏移
	// heading: 水平旋转（左右转）
	// pitch: 俯仰角（上下倾斜）
	// roll: 翻滚角（左右倾斜）
	const headingOffset = cesium.Math.toRadians(110); // 水平旋转110度
	const pitchOffset = cesium.Math.toRadians(0);     // 俯仰角保持水平
	const rollOffset = cesium.Math.toRadians(0);      // 翻滚角保持水平

	const customOrientation = new cesium.CallbackProperty((time, result) => {
		const velocity = velocityOrientation.getValue(time, result);
		if (velocity) {
			const currentPosition = positionProperty.getValue(time);
			if (currentPosition) {
				// 添加额外的旋转偏移（heading, pitch, roll）
				const hpr = new cesium.HeadingPitchRoll(headingOffset, pitchOffset, rollOffset);
				const offset = cesium.Transforms.headingPitchRollQuaternion(
					currentPosition,
					hpr
				);
				return cesium.Quaternion.multiply(velocity, offset, result);
			}
		}
		return velocity;
	}, false);

	/**
	 * @description 创建运动的模型实体
	 * */
	const entity = viewer.entities.add({
		availability: new cesium.TimeIntervalCollection([
			new cesium.TimeInterval({
				start: startTime,
				stop: stopTime,
			}),
		]),
		position: positionProperty,
		// 使用自定义朝向，让模型头部朝向运动方向
		orientation: customOrientation,
		model: {
			uri: model,
			minimumPixelSize: 64,
			maximumScale: 200,
			show: true,
		},
		// 添加飞行轨迹线
		path: {
			resolution: 1,
			material: new cesium.PolylineGlowMaterialProperty({
				glowPower: 0.3,  // 增强发光效果
				color: cesium.Color.CYAN,  // 改为青色更明显
			}),
			width: 8,  // 增加线宽
			leadTime: 0,  // 不显示前方轨迹
			trailTime: 360,  // 显示360秒的历史轨迹
		},
	});

	console.log('模型位置:', longitude, latitude, '地形高度:', terrainHeight);

	/**
	 * @description 多视角自动切换
	 * 在飞行过程中自动切换不同的相机视角
	 * */
	// 定义多个视角配置
	const cameraViews = [
		{ name: '后方跟随视角', heading: 0, pitch: -15, range: 200 },      // 从后方跟随
		{ name: '右侧视角', heading: 90, pitch: -20, range: 250 },          // 从右侧观察
		{ name: '前方视角', heading: 180, pitch: -10, range: 180 },         // 从前方观察
		{ name: '左侧视角', heading: -90, pitch: -25, range: 250 },         // 从左侧观察
		{ name: '俯视视角', heading: 0, pitch: -90, range: 300 },           // 从上方俯视
		{ name: '斜后方视角', heading: 45, pitch: -30, range: 220 },        // 斜后方
	];

	let currentViewIndex = 0;

	// 初始视角设置
	setTimeout(() => {
		viewer.trackedEntity = entity;
		console.log('相机开始跟踪模型，模型正在沿圆形路径飞行');
		
		// 设置初始视角
		const firstView = cameraViews[0];
		viewer.trackedEntity = entity;
		viewer.scene.camera.lookAt(
			entity.position.getValue(viewer.clock.currentTime),
			new cesium.HeadingPitchRange(
				cesium.Math.toRadians(firstView.heading),
				cesium.Math.toRadians(firstView.pitch),
				firstView.range
			)
		);
		console.log(`切换到视角: ${firstView.name}`);
	}, 100);

	// 每隔30秒自动切换视角
	setInterval(() => {
		if (viewer.clock.shouldAnimate) {
			currentViewIndex = (currentViewIndex + 1) % cameraViews.length;
			const view = cameraViews[currentViewIndex];
			
			// 获取当前实体位置
			const currentTime = viewer.clock.currentTime;
			const position = entity.position.getValue(currentTime);
			
			if (position) {
				// 平滑切换到新视角
				viewer.scene.camera.flyTo({
					destination: position,
					orientation: {
						heading: cesium.Math.toRadians(view.heading),
						pitch: cesium.Math.toRadians(view.pitch),
						range: view.range
					},
					duration: 2.0,  // 切换动画持续2秒
					complete: () => {
						// 切换完成后继续跟踪
						viewer.trackedEntity = entity;
						viewer.scene.camera.lookAt(
							position,
							new cesium.HeadingPitchRange(
								cesium.Math.toRadians(view.heading),
								cesium.Math.toRadians(view.pitch),
								view.range
							)
						);
						console.log(`切换到视角: ${view.name}`);
					}
				});
			}
		}
	}, 30000);  // 30秒切换一次

	// 启动时钟动画
	viewer.clock.shouldAnimate = true;
});
</script>

<style scoped>
.cesium-content {
	width: 100%;
	height: calc(100vh - 80px);
	border-radius: 16px;
	overflow: hidden;
	box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
	margin: 20px;
	background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}

:deep(.cesium-viewer) {
	border-radius: 16px;
}

:deep(.cesium-widget-credits) {
	display: none !important;
}
</style>
